﻿/* ----------------------------------------------------------------------------
 * Copyright (c) Philip Stears 
 *
 * This source code is subject to terms and conditions of the Microsoft Public 
 * License (Ms-PL).
 * 
 * By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 * 
 * To request a copy of the Microsoft Public License, send a request by email
 * to license@connectbasic.net.
 *
 * This notice must not be removed from this software.
 * ---------------------------------------------------------------------------- */

namespace ConnectBasic.Execution.Binding
{
    using System;
    using Microsoft.Linq.Expressions;
    using Microsoft.Scripting;

    internal class BasicConvertBinder : ConvertBinder
    {
        public BasicConvertBinder(Type desiredType)
            : base(desiredType, true)
        {
        }

        public override DynamicMetaObject FallbackConvert(DynamicMetaObject self, DynamicMetaObject onBindingError)
        {

            DynamicMetaObject result;

            // COM object?
            if (ComBinder.IsComObject(self.Value))
            {

                // Try getting the default property of the COM object if it has one
                if (ComBinder.TryBindGetIndex(new BasicGetIndexBinder(new CallInfo(0)), self, new DynamicMetaObject[0], out result))
                {

                    // Okay, create a new DMO which will get the default property, and then 
                    // convert the result to the desired type
                    return new DynamicMetaObject(
                        Expression.Dynamic(new BasicConvertBinder(this.Type), this.Type, result.Expression),
                        result.Restrictions
                        );
                }
            }

            // Already a match?
            if (self.RuntimeType == this.Type)
            {
                return new DynamicMetaObject(
                    Expression.Convert(self.Expression, this.Type),
                    BindingRestrictions.GetTypeRestriction(self.Expression, this.Type)
                    );
            }

            // Return an exception
            return onBindingError ?? DynamicMetaObject.CreateThrow(self, EmptyArray<DynamicMetaObject>.Instance, typeof(NotImplementedException), (object[])null);
        }
    }
}
